/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/core/PGLUtility.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

LPCTSTR CPGLUtility::ColorMap2String(EColorMap cm)
{
	switch (cm)
	{
	case ColorMapHsv:
		return _T("HSV");
	case ColorMapJet:
		return _T("Jet");
	case ColorMapGray:
		return _T("Gray");
	case ColorMapPink:
		return _T("Pink");
	case ColorMapCool:
		return _T("Cool");
	case ColorMapBone:
		return _T("Bone");
	case ColorMapCopper:
		return _T("Copper");
	case ColorMapHot:
		return _T("Hot");
	case ColorMapAutumn:
		return _T("Autumn");
	case ColorMapWinter:
		return _T("Winter");
	case ColorMapSpring:
		return _T("Spring");
	case ColorMapSummer:
		return _T("Summer");
	default:
		return _T("HSV");
	}
}

CPGLUtility::EColorMap CPGLUtility::String2ColorMap(LPCTSTR szColorMap)
{
	if (_tcsicmp(szColorMap, _T("HSV"))==0)
		return ColorMapHsv;

	if (_tcsicmp(szColorMap, _T("Jet"))==0)
		return ColorMapJet;
	
	if (_tcsicmp(szColorMap, _T("Gray"))==0)
		return ColorMapGray;
	
	if (_tcsicmp(szColorMap, _T("Pink"))==0)
		return ColorMapPink;

	if (_tcsicmp(szColorMap, _T("Cool"))==0)
		return ColorMapCool;

	if (_tcsicmp(szColorMap, _T("Bone"))==0)
		return ColorMapBone;

	if (_tcsicmp(szColorMap, _T("Copper"))==0)
		return ColorMapCopper;

	if (_tcsicmp(szColorMap, _T("Hot"))==0)
		return ColorMapHot;

	if (_tcsicmp(szColorMap, _T("Autumn"))==0)
		return ColorMapAutumn;

	if (_tcsicmp(szColorMap, _T("Winter"))==0)
		return ColorMapWinter;

	if (_tcsicmp(szColorMap, _T("Spring"))==0)
		return ColorMapSpring;

	if (_tcsicmp(szColorMap, _T("Summer"))==0)
		return ColorMapSummer;
	
	return ColorMapHsv;
}

//#pragma optimize( "", off )
/*
void CPGLUtility::DrawColorMap(gfxinterface::CGfxInterface& gfx, EColorMap eCM, CPGLViewScreen* pView)
{
	CPGLColor col;
	float w,h;
	float x,y;
	
	x=(float)(pView->GetWidth()-20);
	w=10;
	if (x<1)
		return;

	y=(float)(pView->GetHeight()*0.25);
	h=(float)(pView->GetHeight()*0.5);
/*	
	// drawing colormap
	switch(eCM)
	{
	case ColorMapHsv:
		glBegin(GL_QUAD_STRIP);
		// line 0
		HSV(0,col);
		col.MakeCurrent(gfx);
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// line 1
		HSV(1.0/6.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h/6.0f);
		glVertex2f(x+w,y+h/6.0f);
		// line 1
		HSV(1.0/3.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h/3.0f);
		glVertex2f(x+w,y+h/3.0f);
		// line 1
		HSV(0.5f,col);
		col.MakeCurrent();
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x+w,y+h*0.5f);
		// line 1
		HSV(2.0/3.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h*2.0f/3.0f);
		glVertex2f(x+w,y+h*2.0f/3.0f);
		// line 1
		HSV(5.0/6.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h*5.0f/6.0f);
		glVertex2f(x+w,y+h*5.0f/6.0f);
		// line 1
		HSV(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		HSV(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapJet:
		glBegin(GL_QUAD_STRIP);
		// first line
		Jet(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Jet(0.125,col);
		col.MakeCurrent();
		glVertex2f(x,y+0.125f*h);
		glVertex2f(x+w,y+0.125f*h);
		// third line
		Jet(0.375,col);
		col.MakeCurrent();
		glVertex2f(x,y+0.375f*h);
		glVertex2f(x+w,y+0.375f*h);
		// fourth line
		Jet(0.625,col);
		col.MakeCurrent();
		glVertex2f(x,y+0.625f*h);
		glVertex2f(x+w,y+0.625f*h);
		// fifth line
		Jet(0.875,col);
		col.MakeCurrent();
		glVertex2f(x,y+0.875f*h);
		glVertex2f(x+w,y+0.875f*h);
		// sixth line
		Jet(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Jet(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapGray:
		glBegin(GL_QUAD_STRIP);
		// first line
		Gray(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Gray(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Gray(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapPink:
		glBegin(GL_QUAD_STRIP);
		// first line
		Pink(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Pink(3.0/8.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/8.0f*h);
		glVertex2f(x+w,y+3.0f/8.0f*h);
		// line 3
		Pink(3.0/4.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/4.0f*h);
		glVertex2f(x+w,y+3.0f/4.0f*h);
		// line 4
		Pink(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Pink(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapCool:
		glBegin(GL_QUAD_STRIP);
		// first line
		Cool(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Cool(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Cool(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapBone:
		glBegin(GL_QUAD_STRIP);
		// first line
		Bone(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Bone(3.0/8.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/8.0f*h);
		glVertex2f(x+w,y+3.0f/8.0f*h);
		// line 3
		Bone(3.0/4.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/4.0f*h);
		glVertex2f(x+w,y+3.0f/4.0f*h);
		// line 4
		Bone(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Bone(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapCopper:
		glBegin(GL_QUAD_STRIP);
		// first line
		Copper(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Copper(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Copper(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapHot:
		glBegin(GL_QUAD_STRIP);
		// first line
		Hot(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Hot(3.0/8.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/8.0f*h);
		glVertex2f(x+w,y+3.0f/8.0f*h);
		// line 3
		Hot(3.0/4.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+3.0f/4.0f*h);
		glVertex2f(x+w,y+3.0f/4.0f*h);
		// line 4
		Hot(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Hot(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapAutumn:
		glBegin(GL_QUAD_STRIP);
		// first line
		Autumn(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Autumn(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Autumn(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapWinter:
		glBegin(GL_QUAD_STRIP);
		// first line
		Winter(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Winter(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Winter(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
	case ColorMapSpring:
		glBegin(GL_QUAD_STRIP);
		// first line
		Spring(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Spring(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();

		// drawing little triangle...
		Spring(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;

	case ColorMapSummer:
		glBegin(GL_QUAD_STRIP);
		// first line
		Summer(0,col);
		col.MakeCurrent();
		glVertex2f(x,y);
		glVertex2f(x+w,y);
		// second line
		Summer(1.0,col);
		col.MakeCurrent();
		glVertex2f(x,y+h);
		glVertex2f(x+w,y+h);
		glEnd();
		// drawing little triangle...
		Summer(0.5,col);
		col.MakeCurrent();
		glBegin(GL_TRIANGLES);
		glVertex2f(x,y+h*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glVertex2f(x-(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		
		glVertex2f(x+w,y+h*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f-w*0.5f);
		glVertex2f(x+w+(float)(w/sqrt(2.0)),y+h*0.5f+w*0.5f);
		glEnd();
		break;
		}

		// drawing rectangle
		gfx.DrawRect(x,y,x+w,y+h);

		// drawing middle
		gfx.DrawLine(x,y+h*0.5f,x+w,y+h*0.5f);
}
*/

void CPGLUtility::ColorMap(EColorMap eCM, double alpha, CPGLColor& col)
{
	alpha = __min( 1, __max( 0, alpha));
	switch(eCM)
	{
	case ColorMapHsv:
		HSV(alpha,col);
		break;
	case ColorMapJet:
		Jet(alpha,col);
		break;
	case ColorMapGray:
		Gray(alpha,col);
		break;
	case ColorMapPink:
		Pink(alpha,col);
		break;
	case ColorMapCool:
		Cool(alpha,col);
		break;
	case ColorMapBone:
		Bone(alpha,col);
		break;
	case ColorMapCopper:
		Copper(alpha,col);
		break;
	case ColorMapHot:
		Hot(alpha,col);
		break;
	case ColorMapAutumn:
		Autumn(alpha,col);
		break;
	case ColorMapWinter:
		Winter(alpha,col);
		break;
	case ColorMapSpring:
		Spring(alpha,col);
		break;
	case ColorMapSummer:
		Summer(alpha,col);
		break;
	}
}


/// Black-red-yellow-white color map
void CPGLUtility::HSV(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	
	double h=alpha*6;
	double s=1.0;
	double v=1.0;

	int k=(int)floor(h);
	double f=h-k;
	float t=(float)(1.0-s);
	float n=(float)(1.0-s*f);
	float p=(float)((1.0-(s*(1.0-f))));
	float e=1.0f;

	// reshaping
	float scale;

	switch(k)
	{
	case 0:
		scale=1.0f/(__max(e, __max(p, t)));
		e*=scale;
		p*=scale;
		t*=scale;
		col.SetColor(e,p,t);
		break;
	case 1:
		scale=1.0f/(__max(e, __max(n, t)));
		e*=scale;
		n*=scale;
		t*=scale;
		col.SetColor(n,e,t);
		break;
	case 2:
		scale=1.0f/(__max(e, __max(p, t)));
		e*=scale;
		p*=scale;
		t*=scale;
		col.SetColor(t,e,p);
		break;
	case 3:
		scale=1.0f/(__max(n, __max(p, 1)));
		n*=scale;
		t*=scale;
		col.SetColor(t,n,1);
		break;
	case 4:
		scale=1.0f/(__max(t, __max(p, 1)));
		p*=scale;
		t*=scale;
		col.SetColor(p,t,1);
		break;
	case 5:
		scale=1.0f/(__max(e, __max(n, t)));
		e*=scale;
		n*=scale;
		t*=scale;
		col.SetColor(e,t,n);
		break;
	}

}

void CPGLUtility::Jet(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	if (alpha<=0.125)
	{
		col.SetColor(0,0,(float)((0.125+alpha)/0.25));
	}
	else if (alpha<=0.375)
	{
		col.SetColor(0,
			(float)((alpha-0.125)/0.25),
			1.0f);
	}
	else if (alpha<=0.625)
	{
		col.SetColor((float)((alpha-0.375)/0.25),
				1.0f,
				(float)(1.0-(alpha-0.375)/0.25));
	}
	else if (alpha<=0.875)
	{
		col.SetColor(1.0f,
			(float)(1.0-(alpha-0.625)/0.25),
			0.0f);
	}
	else
	{
		col.SetColor((float)(1.0-(alpha-0.875)/0.25),
			0.0,0.0);
	}
}

void CPGLUtility::Gray(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	col.SetColor((float)alpha,(float)alpha,(float)alpha);
}

void CPGLUtility::Pink(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	static CPGLColor vh;

	Hot(alpha,vh);

	col.SetColor((float)sqrt((2*alpha + vh.GetRed())/3),
		(float)sqrt((2*alpha + vh.GetGreen())/3),
		(float)sqrt((2*alpha + vh.GetBlue())/3));
}

void CPGLUtility::Cool(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	col.SetColor((float)alpha,
		1.0f-(float)alpha,
		1.0f);
}

void CPGLUtility::Bone(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	static CPGLColor vh;

	Hot(alpha,vh);

	col.SetColor((float)((7.0*alpha+vh.GetBlue())/8.0),
		(float)((7.0*alpha+vh.GetGreen())/8.0),
		(float)((7.0*alpha+vh.GetRed())/8.0));
}

void CPGLUtility::Copper(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	col.SetColor((float)__min(1.0,alpha*1.25),
		(float)__min(1.0,alpha*0.7812),
		(float)__min(1.0,alpha*0.4975));
}

void CPGLUtility::Hot(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	static const double c38=3.0/8.0;
	if (alpha<=c38)
	{
			col.SetColor((float)(alpha/c38),
			0,0);
	}
	else if (alpha<=2*c38)
	{
		col.SetColor(1.0f,
			(float)((alpha-c38)/c38),
			0);
	}
	else
	{
		col.SetColor(1.0f,1.0f,
		(float)((alpha-2*c38)/(1.0-2*c38)));
	}
}

void CPGLUtility::Autumn(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	col.SetColor(1.0f,
		(float)alpha,
		0);
}

void CPGLUtility::Winter(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	col.SetColor(0.0,
		(float)alpha,
		(float)(0.5+(1.0-alpha)/2.0));
}

void CPGLUtility::Spring(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);
	col.SetColor(1.0f,
		(float)alpha,
		(float)(1.0-alpha));
}

void CPGLUtility::Summer(double alpha, CPGLColor& col)
{
	ASSERT(alpha<=1.0);
	ASSERT(alpha>=0.0);

	col.SetColor((float)alpha,
		(float)(0.5+alpha/2.0),
		0.4f);
}


void CPGLUtility::PeekAndPump()
{
    MSG msg;
    while (::PeekMessage(&msg, NULL,0,0,PM_NOREMOVE)) 
    {
        if (!AfxGetApp()->PumpMessage()) 
        {
            ::PostQuitMessage(0);
            return;
        } 
    }
}
